// import com.alibaba.druid.sql.SQLUtils;
// import com.alibaba.druid.sql.ast.*;
// import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
// import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
// import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
// import com.alibaba.druid.sql.repository.SchemaObject;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;
// import com.alibaba.druid.util.FnvHash;
// import com.alibaba.druid.util.StringUtils;

// import java.util.ArrayList;
// import java.util.List;
#pragma once

#include <string>
#include <list>

#include "../SQLExpr.h"
#include "../SQLExprImpl.h"
#include "../Object.h"
#include "../SQLName.h"
#include "../SQLReplaceable.h"

#include "SQLTableSourceImpl.h"
#include "SQLTableSampling.h"
#include "../../../utils/common_ptr.h"

class SQLExprTableSource : virtual public SQLTableSourceImpl, virtual public SQLReplaceable
{
private:
  // SHAREDOBJECT(SQLExprTableSource);
  std::shared_ptr<SQLExprTableSource> SharedObject()
  {
    std::weak_ptr<SQLExprTableSource> weakPtr = std::shared_ptr<SQLExprTableSource>(this);
    std::shared_ptr<SQLExprTableSource> sptr = weakPtr.lock();
    return sptr;
  }

public:
  static string_ptr class_;
  SQLExpr_ptr expr;
  SQLName_list_ptr partitions;
  SQLTableSampling_ptr sampling;
  SchemaObject_ptr schemaObject;

  SQLName_list_ptr columns;

  SQLExprTableSource();

  SQLExprTableSource(string_ptr tableName);

  SQLExprTableSource(SQLExpr_ptr expr);

  SQLExprTableSource(SQLExpr_ptr expr, string_ptr alias);
  SHAREDOBJECT(SQLExprTableSource);

  SQLExpr_ptr getExpr();

  void setExpr(SQLExpr_ptr x);

  void setExpr(string_ptr name);

  SQLTableSampling_ptr getSampling();

  void setSampling(SQLTableSampling_ptr x);

  SQLName_ptr getName();

  string_ptr getTableName(BOOL_ptr normalize);

  string_ptr getTableName();

  string_ptr getSchema();

  string_ptr getCatalog();

  BOOL_ptr setCatalog(string_ptr catalog);

  void setCatalog(string_ptr catalog, string_ptr schema);

  void setSchema(string_ptr schema);

  void setSimpleName(string_ptr name);

  SQLName_list_ptr getPartitions();

  int getPartitionSize();

  void addPartition(SQLName_ptr partition);

  void accept0(SQLASTVisitor_ptr visitor) override;

  // string_ptr  computeAlias() {
  //     string_ptr  alias = this->getAlias();

  //     if (alias == NULL) {
  //         if (expr instanceof SQLName) {
  //             alias = ((SQLName) expr).getSimpleName();
  //         }
  //     }

  //     return SQLUtils.normalize(alias);
  // }

  // SQLExprTableSource_ptr  clone() ;
  virtual SQLObject_ptr clone();

  void cloneTo(SQLExprTableSource_ptr x);

  SQLName_list_ptr getColumns();

  SQLName_list_ptr getColumnsDirect();

  SchemaObject_ptr getSchemaObject();

  void setSchemaObject(SchemaObject_ptr schemaObject);

  // BOOL_ptr containsAlias(string_ptr  alias) {
  //     long hashCode64 = FnvHash.hashCode64(alias);

  //     return containsAlias(hashCode64);
  // }

  BOOL_ptr containsAlias(long aliasHash);

  // SQLColumnDefinition* findColumn(string_ptr  columnName) ;

  // SQLColumnDefinition* findColumn(long columnNameHash) ;

  // SQLObject* resolveColum(long columnNameHash) {
  //     if (schemaObject != NULL) {
  //         SQLStatement stmt = schemaObject.getStatement();
  //         if (stmt instanceof SQLCreateTableStatement) {
  //             SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) stmt;
  //             return createTableStmt.findColumn(columnNameHash);
  //         }
  //     }

  //     SQLObject resolvedOwnerObject = NULL;
  //     if (expr instanceof SQLIdentifierExpr) {
  //         resolvedOwnerObject = ((SQLIdentifierExpr) expr).getResolvedOwnerObject();
  //     }

  //     if (resolvedOwnerObject == NULL) {
  //         return resolvedOwnerObject;
  //     }

  //     if (resolvedOwnerObject instanceof SQLWithSubqueryClause.Entry) {
  //         final SQLSelect subQuery = ((SQLWithSubqueryClause.Entry) resolvedOwnerObject)
  //                 .getSubQuery();
  //         if (subQuery == NULL) {
  //             return NULL;
  //         }

  //         final SQLSelectQueryBlock firstQueryBlock = subQuery.getFirstQueryBlock();
  //         if (firstQueryBlock == NULL) {
  //             return NULL;
  //         }

  //         SQLSelectItem selectItem = firstQueryBlock.findSelectItem(columnNameHash);
  //         if (selectItem != NULL) {
  //             return selectItem;
  //         }
  //     }
  //     return NULL;
  // }

  SQLTableSource_ptr findTableSourceWithColumn(string_ptr columnName);
  SQLTableSource_ptr findTableSourceWithColumn(long columnName_hash, string_ptr name, int option);
  SQLTableSource_ptr findTableSource(long alias_hash);

  BOOL_ptr replace(SQLExpr_ptr expr, SQLExpr_ptr target);

  long aliasHashCode64();

  bool equals(Object_ptr o);

  int hashCode();

  virtual SQLColumnDefinition_ptr findColumn(string_ptr columnName) override{};
  virtual SQLColumnDefinition_ptr findColumn(long columnNameHash) override{};
};
